GtkColorEditor: Keep ref on pre-popup focus widget
authorCarlos Garnacho <carlosg@gnome.org>
Tue, 21 Jun 2016 11:57:20 +0000 (13:57 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Tue, 21 Jun 2016 15:56:34 +0000 (17:56 +0200)
And ensure it's still visible before returning the keyboard focus to it.
Because of the extra ref, add a dispose handler that will ensure the
ref is lost (by popping down), although this should be already ensured
through other paths (eg. when the popup widget loses visibility).

This fixes a possible crash in dispose paths, where we might be restoring
focus on an already destroyed widget, and at a time where, if the toplevel
is being itself disposed, no new focus should be set.

https://bugzilla.gnome.org/show_bug.cgi?id=767849

gtk/gtkcoloreditor.c

index f45949c999a623b7b97f5720101df1954f10a1ef..ed8f48b7a7ba53378310ac88be44bfd4f65aa51a 100644 (file)
@@ -175,8 +175,9 @@ dismiss_current_popup (GtkColorEditor *editor)
       editor->priv->popup_position = 0;
       if (editor->priv->popdown_focus)
         {
-          gtk_widget_grab_focus (editor->priv->popdown_focus);
-          editor->priv->popdown_focus = NULL;
+          if (gtk_widget_is_visible (editor->priv->popdown_focus))
+            gtk_widget_grab_focus (editor->priv->popdown_focus);
+          g_clear_object (&editor->priv->popdown_focus);
         }
     }
 }
@@ -218,7 +219,7 @@ popup_edit (GtkWidget      *widget,
     {
       dismiss_current_popup (editor);
       toplevel = gtk_widget_get_toplevel (GTK_WIDGET (editor));
-      editor->priv->popdown_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+      g_set_object (&editor->priv->popdown_focus, gtk_window_get_focus (GTK_WINDOW (toplevel)));
       editor->priv->current_popup = popup;
       editor->priv->popup_position = position;
       gtk_widget_show (popup);
@@ -395,6 +396,16 @@ gtk_color_editor_init (GtkColorEditor *editor)
   gtk_style_context_remove_class (gtk_widget_get_style_context (editor->priv->swatch), "activatable");
 }
 
+static void
+gtk_color_editor_dispose (GObject *object)
+{
+  GtkColorEditor *editor = GTK_COLOR_EDITOR (object);
+
+  dismiss_current_popup (editor);
+
+  G_OBJECT_CLASS (gtk_color_editor_parent_class)->dispose (object);
+}
+
 static void
 gtk_color_editor_get_property (GObject    *object,
                                guint       prop_id,
@@ -463,6 +474,7 @@ gtk_color_editor_class_init (GtkColorEditorClass *class)
   GObjectClass *object_class = G_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
 
+  object_class->dispose = gtk_color_editor_dispose;
   object_class->get_property = gtk_color_editor_get_property;
   object_class->set_property = gtk_color_editor_set_property;